package com.lokyiu.mybible.wol;

import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;

import com.lokyiu.mybible.domain.BibleBook;
import com.lokyiu.mybible.domain.Chapter;
import com.lokyiu.mybible.domain.Verse;

public class ContentDownloader {
	//private static final String WOL_NWT_URL = "http://wol.jw.org/zh-Hant/wol/binav/r24/lp-ch/bi12/CH/2001";

	/**
	 * Converts a String to a Number
	 * @param str
	 * @return
	 */
	private static Number toNumeric(String str) {
		NumberFormat formatter = NumberFormat.getInstance();
		ParsePosition pos = new ParsePosition(0);
		return formatter.parse(str, pos);
	}
	
	/**
	 * Tests if a String is a number
	 * @param str
	 * @return
	 */
	private static boolean isNumeric(String str) {
		NumberFormat formatter = NumberFormat.getInstance();
		ParsePosition pos = new ParsePosition(0);
		formatter.parse(str, pos);
		return str.length() != 0 && str.length() == pos.getIndex();
	}

	/**
	 * Extracts the id shortcut from a link
	 * @param href
	 * @return
	 */
	private String getIdFromHref(String href) {
		int hashIndex = href.indexOf("#");
		return href.substring(hashIndex);
	}
	
	/**
	 * Returns a list of all the bible books from WOL.
	 * @return
	 */
	
	public List<BibleBook> getBibleBooks(DocumentFactory df) throws InvalidContentException {
		List<BibleBook> bibleBooks = new ArrayList<BibleBook>();
		Elements bibleNode = df.getDocument().select("div.bible");
		if (bibleNode == null) {
			throw new InvalidContentException();
		}
		Elements linkNodes = bibleNode.select("a[href]");
		if (linkNodes == null) {
			throw new InvalidContentException();
		}
		for(Element linkNode : linkNodes){
			Elements nameNode = linkNode.select("span.name");
			BibleBook book = new BibleBook(nameNode.text(),linkNode.attr("abs:href"));
			bibleBooks.add(book);
		}
		return bibleBooks;
	}

	/**
	 * Returns a list of all the chapters for a given book from WOL.
	 * @param book
	 * @return
	 */
	public List<Chapter> getChapters(DocumentFactory df, BibleBook book) {
		List<Chapter> chapters = new ArrayList<Chapter>();
		Elements chapterNode = df.getDocument().select("ul.chapters");
		Elements chapterLinks = chapterNode.select("a[href]");
		for(Element chapterLink : chapterLinks){
			if (isNumeric(chapterLink.text())){
				Chapter chapter = new Chapter(book.getName(),Integer.parseInt(chapterLink.text()),chapterLink.attr("abs:href"));
				chapters.add(chapter);
			}
		}
		return chapters;
	}
	
	/**
	 * Returns a list of all the verses for a given book from WOL.
	 * This method is used for books with only one chapter, e.g. Jude.
	 * @param book
	 * @return
	 */
	public List<Verse> getVerses(DocumentFactory df, BibleBook book) {
		return getVerses(df, book.getName(), 1);
	}
	
	/**
	 * Returns a list of all the verses for a given chapter from WOL.
	 * This method is used for books with more than one chapter.
	 * @param chapter
	 * @return
	 */
	public List<Verse> getVerses(DocumentFactory df, Chapter chapter) {
		return getVerses(df, chapter.getBibleBook(), chapter.getChapterNumber());
	}
	
	/**
	 * This method retrieves all the verses from a url.  This method
	 * assumes WOL handles verses the same way for books with one chapter
	 * as books with more than one chapter.
	 * @param book
	 * @param chapter
	 * @param url
	 * @return
	 */
	private List<Verse> getVerses(DocumentFactory df, String book, int chapter) {
		List<Verse> verses = new ArrayList<Verse>();
		Elements navVersesNode = df.getDocument().select("div.navVerses");
		Elements versesLinks = navVersesNode.select("a[class=verseItem]");
		Set<String> verseIdSet = new HashSet<String>();
		for(Element verseLink : versesLinks){
			String href = verseLink.attr("abs:href");
			String verseId = getIdFromHref(href);  
			verseIdSet.add(verseId);
		}
		Elements versesNode = df.getDocument().select("div[class=document bible]");
		for(Element versesLink : versesLinks){
				String verseNumber = versesLink.ownText();
				String verseId = getIdFromHref(versesLink.attr("href"));
				Elements verseSpans = versesNode.select("span" + verseId);
				Element verseSpan = verseSpans.first();
				Node siblingOfSpan = verseSpan.nextSibling();
				StringBuilder content = new StringBuilder();
				while(siblingOfSpan != null){
					if (siblingOfSpan instanceof TextNode){
						content.append(siblingOfSpan);
					}else if(verseIdSet.contains("#" + siblingOfSpan.attr("id"))){
						break;
					}
					siblingOfSpan = siblingOfSpan.nextSibling();
				}

				Verse verse = new Verse(book,chapter,Integer.parseInt(verseNumber),content.toString());
				verses.add(verse);
		}
		return verses;
	}
}
